// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// asm包为汇编程序实现解析器和指令生成器。
// 待办事项：分开？
package asm

import (
	"fmt"
	"io"
	"log"
	"os"
	"strconv"
	"text/scanner"
	"unicode/utf8"

	"cmd/asm/internal/arch"
	"cmd/asm/internal/flags"
	"cmd/asm/internal/lex"
	"cmd/internal/obj"
	"cmd/internal/obj/x86"
	"cmd/internal/src"
	"cmd/internal/sys"
)

type Parser struct {
	lex              lex.TokenReader
	lineNum          int   // 源文件中的行号。
	errorLine        int   // 最后一个错误的行号。
	errorCount       int   // 错误数。
	sawCode          bool  // 在该文件中看到了代码（与注释和空行相反）
	pc               int64 // 虚拟PC；程序计数；不适用于GLOBL或DATA。
	input            []lex.Token
	inputPos         int
	pendingLabels    []string // 要附加到下一条指令的标签。
	labels           map[string]*obj.Prog
	toPatch          []Patch
	addr             []obj.Addr
	arch             *arch.Arch
	ctxt             *obj.Link
	firstProg        *obj.Prog
	lastProg         *obj.Prog
	dataAddr         map[string]int64 // 此符号数据的最新地址。
	isJump           bool             // 正在组装的指令是一个跳转。
	compilingRuntime bool
	errorWriter      io.Writer
}

type Patch struct {
	prog  *obj.Prog
	label string
}

func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader, compilingRuntime bool) *Parser {
	return &Parser{
		ctxt:             ctxt,
		arch:             ar,
		lex:              lexer,
		labels:           make(map[string]*obj.Prog),
		dataAddr:         make(map[string]int64),
		errorWriter:      os.Stderr,
		compilingRuntime: compilingRuntime,
	}
}

// 在测试第一个错误
// 并将其转化为可恢复的恐慌时，启用panicOnError。
var panicOnError bool

func (p *Parser) errorf(format string, args ...interface{}) {
	if panicOnError {
		panic(fmt.Errorf(format, args...))
	}
	if p.lineNum == p.errorLine {
		// 每行只有一个错误。
		return
	}
	p.errorLine = p.lineNum
	if p.lex != nil {
		// 将文件和行信息放在消息的开头。
		format = "%s:%d: " + format + "\n"
		args = append([]interface{}{p.lex.File(), p.lineNum}, args...)
	}
	fmt.Fprintf(p.errorWriter, format, args...)
	p.errorCount++
	if p.errorCount > 10 && !*flags.AllErrors {
		log.Fatal("too many errors")
	}
}

func (p *Parser) pos() src.XPos {
	return p.ctxt.PosTable.XPos(src.MakePos(p.lex.Base(), uint(p.lineNum), 0))
}

func (p *Parser) Parse() (*obj.Prog, bool) {
	scratch := make([][]lex.Token, 0, 3)
	for {
		word, cond, operands, ok := p.line(scratch)
		if !ok {
			break
		}
		scratch = operands

		if p.pseudo(word, operands) {
			continue
		}
		i, present := p.arch.Instructions[word]
		if present {
			p.instruction(i, word, cond, operands)
			continue
		}
		p.errorf("unrecognized instruction %q", word)
	}
	if p.errorCount > 0 {
		return nil, false
	}
	p.patch()
	return p.firstProg, true
}

// ParseSymABIs解析p的汇编代码以查找文本符号
// 定义和引用，并将一个symabis文件写入w。
func (p *Parser) ParseSymABIs(w io.Writer) bool {
	operands := make([][]lex.Token, 0, 3)
	for {
		word, _, operands1, ok := p.line(operands)
		if !ok {
			break
		}
		operands = operands1

		p.symDefRef(w, word, operands)
	}
	return p.errorCount == 0
}

// nextToken从lexer返回下一个非构建注释标记。
// 它报告了放错位置的
func (p *Parser) nextToken() lex.ScanToken {
	for {
		tok := p.lex.Next()
		if tok == lex.BuildComment {
			if p.sawCode {
				p.errorf("misplaced // go:build comment“）
			}
			continue
		}
		if tok != '\n' {
			p.sawCode = true
		}
		if tok == '#' {
			// A#include/#define/etc，
			// 让我们知道p.sawCode现在应该是真的。
			// 否则被忽略。
			continue
		}
		return tok
	}
}

// 生产线消耗p.lex中的一条装配线，形式为
// 
// 
// 它向p.pendingLabels添加任何标签，并返回单词、cond、
// 操作数列表和true。如果出现错误或EOF，则返回
// ok=false。
// 
// line可以从头开始重用内存。
func (p *Parser) line(scratch [][]lex.Token) (word, cond string, operands [][]lex.Token, ok bool) {
next:
	// 跳过换行符。
	var tok lex.ScanToken
	for {
		tok = p.nextToken()
		// 我们将行号保存在这里，因此来自此指令
		// 的错误消息将标记为此行。否则，我们在吸收
		// 终止换行和行号错误后会投诉。
		p.lineNum = p.lex.Line()
		switch tok {
		case '\n', ';':
			continue
		case scanner.EOF:
			return "", "", nil, false
		}
		break
	}
	// 第一项必须是标识符。
	if tok != scanner.Ident {
		p.errorf("expected identifier, found %q", p.lex.Text())
		return "", "", nil, false // 不如现在就停下来。
	}
	word, cond = p.lex.Text(), ""
	operands = scratch[:0]
	// 零个或多个逗号分隔的操作数，每个循环一个。
	nesting := 0
	colon := -1
	for tok != '\n' && tok != ';' {
		// 处理一个操作数。
		var items []lex.Token
		if cap(operands) > len(operands) {
			// 重复使用临时项目。
			items = operands[:cap(operands)][len(operands)][:0]
		} else {
			items = make([]lex.Token, 0, 3)
		}
		for {
			tok = p.nextToken()
			if len(operands) == 0 && len(items) == 0 {
				if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386) && tok == '.' {
					// 后缀：ARM条件或x86修饰符。
					tok = p.nextToken()
					str := p.lex.Text()
					if tok != scanner.Ident {
						p.errorf("instruction suffix expected identifier, found %s", str)
					}
					cond = cond + "." + str
					continue
				}
				if tok == ':' {
					// 标签。
					p.pendingLabels = append(p.pendingLabels, word)
					goto next
				}
			}
			if tok == scanner.EOF {
				p.errorf("unexpected EOF")
				return "", "", nil, false
			}
			// 在逗号上拆分操作数。此外，x86上“寄存器对”
			// 的旧语法是AX:DX，新语法是DX，AX。注意重新排序。
			if tok == '\n' || tok == ';' || (nesting == 0 && (tok == ',' || tok == ':')) {
				if tok == ':' {
					// 记住这个位置，这样我们就可以交换下面的操作数了。
					if colon >= 0 {
						p.errorf("invalid ':' in operand")
						return word, cond, operands, true
					}
					colon = len(operands)
				}
				break
			}
			if tok == '(' || tok == '[' {
				nesting++
			}
			if tok == ')' || tok == ']' {
				nesting--
			}
			items = append(items, lex.Make(tok, p.lex.Text()))
		}
		if len(items) > 0 {
			operands = append(operands, items)
			if colon >= 0 && len(operands) == colon+2 {
				// AX:DX变成DX，AX。
				operands[colon], operands[colon+1] = operands[colon+1], operands[colon]
				colon = -1
			}
		} else if len(operands) > 0 || tok == ',' || colon >= 0 {
			// 有一个分隔符，后面什么都没有。
			p.errorf("missing operand")
		}
	}
	return word, cond, operands, true
}

func (p *Parser) instruction(op obj.As, word, cond string, operands [][]lex.Token) {
	p.addr = p.addr[0:0]
	p.isJump = p.arch.IsJump(word)
	for _, op := range operands {
		addr := p.address(op)
		if !p.isJump && addr.Reg < 0 { // 跳转指的是PC，一个伪。
			p.errorf("illegal use of pseudo-register in %s", word)
		}
		p.addr = append(p.addr, addr)
	}
	if p.isJump {
		p.asmJump(op, cond, p.addr)
		return
	}
	p.asmInstruction(op, cond, p.addr)
}

func (p *Parser) pseudo(word string, operands [][]lex.Token) bool {
	switch word {
	case "DATA":
		p.asmData(operands)
	case "FUNCDATA":
		p.asmFuncData(operands)
	case "GLOBL":
		p.asmGlobl(operands)
	case "PCDATA":
		p.asmPCData(operands)
	case "PCALIGN":
		p.asmPCAlign(operands)
	case "TEXT":
		p.asmText(operands)
	default:
		return false
	}
	return true
}

// symDefRef扫描一行，寻找潜在的文本符号定义，并将symabis信息引用和写入w。
// 
// symabis格式记录在
// cmd compile/internal/ssagen中。ReadSymABIs。
func (p *Parser) symDefRef(w io.Writer, word string, operands [][]lex.Token) {
	switch word {
	case "TEXT":
		// 定义操作数[0]中的文本符号。
		if len(operands) > 0 {
			p.start(operands[0])
			if name, abi, ok := p.funcAddress(); ok {
				fmt.Fprintf(w, "def %s %s\n", name, abi)
			}
		}
		return
	case "GLOBL", "PCDATA":
		// 没有文本定义或符号引用。
	case "DATA", "FUNCDATA":
		// 对于数据，操作数[0]定义为符号。
		// 对于FUNCDATA，操作数[0]是立即数常量。
		// 剩余的操作数可能有引用。
		if len(operands) < 2 {
			return
		}
		operands = operands[1:]
	}
	// 搜索符号引用。
	for _, op := range operands {
		p.start(op)
		if name, abi, ok := p.funcAddress(); ok {
			fmt.Fprintf(w, "ref %s %s\n", name, abi)
		}
	}
}

func (p *Parser) start(operand []lex.Token) {
	p.input = operand
	p.inputPos = 0
}

// 地址将操作数解析为链接地址结构。
func (p *Parser) address(operand []lex.Token) obj.Addr {
	p.start(operand)
	addr := obj.Addr{}
	p.operand(&addr)
	return addr
}

// parseScale将十进制字符串转换为有效的比例因子。
func (p *Parser) parseScale(s string) int8 {
	switch s {
	case "1", "2", "4", "8":
		return int8(s[0] - '0')
	}
	p.errorf("bad scale: %s", s)
	return 0
}

// 操作数解析一般操作数并将结果存储在*a中。
func (p *Parser) operand(a *obj.Addr) {
	// fmt。Printf（“操作数：%v\n”，p.input）
	if len(p.input) == 0 {
		p.errorf("empty operand: cannot happen")
		return
	}
	// 一般地址（除少数例外）看起来像
	// /$sym±offset（SB）（reg）（index*scale）
	// 例外情况是：
	// 
	// R1 
	// /$offset 
	// 每件都是可选的，所以我们从左到右扫描
	// 我们发现的东西告诉我们我们在哪里。

	// 前缀：$。我们有一个符号。解析$sym±偏移量（symkind）
	var prefix rune
	switch tok := p.peek(); tok {
	case '$', '*':
		prefix = rune(tok)
		p.next()
	}

	tok := p.next()
	name := tok.String()
	if tok.ScanToken == scanner.Ident && !p.atStartOfRegister(name) {
		p.symbolReference(a, name, prefix)
		// fmt。Printf（“SYM%s\n”，obj.Dconv（&emptyProg，0，a））
		if p.peek() == scanner.EOF {
			return
		}
	}

	// arm的特殊寄存器列表语法：[R1，R3-R7]
	if tok.ScanToken == '[' {
		if prefix != 0 {
			p.errorf("illegal use of register list")
		}
		p.registerList(a)
		p.expectOperandEnd()
		return
	}

	// 寄存器：R1 
	if tok.ScanToken == scanner.Ident && p.atStartOfRegister(name) {
		if p.atRegisterShift() {
			// arm移位寄存器，如R1<<R2或R1>>2。
			a.Type = obj.TYPE_SHIFT
			a.Offset = p.registerShift(tok.String(), prefix)
			if p.peek() == '(' {
				// 这里只能是一个文本寄存器。
				p.next()
				tok := p.next()
				name := tok.String()
				if !p.atStartOfRegister(name) {
					p.errorf("expected register; found %s", name)
				}
				a.Reg, _ = p.registerReference(name)
				p.get(')')
			}
		} else if p.atRegisterExtension() {
			a.Type = obj.TYPE_REG
			p.registerExtension(a, tok.String(), prefix)
			p.expectOperandEnd()
			return
		} else if r1, r2, scale, ok := p.register(tok.String(), prefix); ok {
			if scale != 0 {
				p.errorf("expected simple register reference")
			}
			a.Type = obj.TYPE_REG
			a.Reg = r1
			if r2 != 0 {
				// 形式为R1:R2。它在RHS上，第二个寄存器
				// 需要进入LHS。
				panic("cannot happen (Addr.Reg2)")
			}
		}
		// fmt。Printf（“REG%s\n”，obj.Dconv（&emptyProg，0，a））
		p.expectOperandEnd()
		return
	}

	// 常量。
	haveConstant := false
	switch tok.ScanToken {
	case scanner.Int, scanner.Float, scanner.String, scanner.Char, '+', '-', '~':
		haveConstant = true
	case '(':
		// 可以是带括号的表达式或（R）。不过，肯定有什么。
		tok := p.next()
		if tok.ScanToken == scanner.EOF {
			p.errorf("missing right parenthesis")
			return
		}
		rname := tok.String()
		p.back()
		haveConstant = !p.atStartOfRegister(rname)
		if !haveConstant {
			p.back() // 放回“（”.
		}
	}
	if haveConstant {
		p.back()
		if p.have(scanner.Float) {
			if prefix != '$' {
				p.errorf("floating-point constant must be an immediate")
			}
			a.Type = obj.TYPE_FCONST
			a.Val = p.floatExpr()
			// fmt.Printf（“FCONST%s\n”，obj.Dconv（&emptyProg，0，a））
			p.expectOperandEnd()
			return
		}
		if p.have(scanner.String) {
			if prefix != '$' {
				p.errorf("string constant must be an immediate")
				return
			}
			str, err := strconv.Unquote(p.get(scanner.String).String())
			if err != nil {
				p.errorf("string parse error: %s", err)
			}
			a.Type = obj.TYPE_SCONST
			a.Val = str
			// fmt。Printf（“SCONST%s\n”，obj.Dconv（&emptyProg，0，a））
			p.expectOperandEnd()
			return
		}
		a.Offset = int64(p.expr())
		if p.peek() != '(' {
			switch prefix {
			case '$':
				a.Type = obj.TYPE_CONST
			case '*':
				a.Type = obj.TYPE_INDIR // 可以出现，但不合法，链接器将拒绝。
			default:
				a.Type = obj.TYPE_MEM
			}
			// fmt。Printf（“CONST%d%s\n”，a.Offset，obj.Dconv（&emptyProg，0，a））
			p.expectOperandEnd()
			return
		}
		// fmt。Printf（“偏移量%d\n”，a.offset）
	}

	// 寄存器间接寻址：（reg）或（索引*刻度）。我们正处于开局阶段。
	p.registerIndirect(a, prefix)
	// fmt。Printf（“完成%s\n”，p.arch.Dconv（&emptyProg，0，a））

	p.expectOperandEnd()
	return
}

// atstartofrester报告解析器是否位于寄存器定义的开头。
func (p *Parser) atStartOfRegister(name string) bool {
	// 简单寄存器：R10。
	_, present := p.arch.Register[name]
	if present {
		return true
	}
	// 括号内的寄存器：R（10）。
	return p.arch.RegisterPrefix[name] && p.peek() == '('
}

// atRegisterShift报告我们是否在ARM移位寄存器的开始处。
// 我们已经使用了寄存器或R前缀。
func (p *Parser) atRegisterShift() bool {
	// 仅限手臂。
	if !p.arch.InFamily(sys.ARM, sys.ARM64) {
		return false
	}
	// R1<<。。。
	if lex.IsRegisterShift(p.peek()) {
		return true
	}
	// R（1）<<。。。难看的支票。TODO:重新思考我们如何处理ARM寄存器移位，使其不那么特别。
	if p.peek() != '(' || len(p.input)-p.inputPos < 4 {
		return false
	}
	return p.at('(', scanner.Int, ')') && lex.IsRegisterShift(p.input[p.inputPos+3].ScanToken)
}

// atRegisterExtension报告我们是否在ARM64扩展寄存器的开始处。
// 我们已经使用了寄存器或R前缀。
func (p *Parser) atRegisterExtension() bool {
	// 仅限ARM64。
	if p.arch.Family != sys.ARM64 {
		return false
	}
	// R1。xxx 
	if p.peek() == '.' {
		return true
	}
	return false
}

// registerReference解析给定名称R10或括号形式SPR（10）的寄存器。
func (p *Parser) registerReference(name string) (int16, bool) {
	r, present := p.arch.Register[name]
	if present {
		return r, true
	}
	if !p.arch.RegisterPrefix[name] {
		p.errorf("expected register; found %s", name)
		return 0, false
	}
	p.get('(')
	tok := p.get(scanner.Int)
	num, err := strconv.ParseInt(tok.String(), 10, 16)
	p.get(')')
	if err != nil {
		p.errorf("parsing register list: %s", err)
		return 0, false
	}
	r, ok := p.arch.RegisterNumber(name, int16(num))
	if !ok {
		p.errorf("illegal register %s(%d)", name, r)
		return 0, false
	}
	return r, true
}

// 寄存器解析不存在符号的完整寄存器引用（如在4（R0）或R（10）中，但不存在sym（SB））
// 包括涉及多个寄存器的形式，如R1:R2。
func (p *Parser) register(name string, prefix rune) (r1, r2 int16, scale int8, ok bool) {
	// R1或R（1）R1:R2 R1、R2 R1+R2或R1*刻度。
	r1, ok = p.registerReference(name)
	if !ok {
		return
	}
	if prefix != 0 && prefix != '*' { // /*AX正常。
		p.errorf("prefix %c not allowed for register: %c%s", prefix, prefix, name)
	}
	c := p.peek()
	if c == ':' || c == ',' || c == '+' {
		// 第二寄存器；语法（R1+R2）等。没有两种体系结构是一致的。
		// 检查架构是否与语法匹配。
		switch p.next().ScanToken {
		case ',':
			if !p.arch.InFamily(sys.ARM, sys.ARM64) {
				p.errorf("(register,register) not supported on this architecture")
				return
			}
		case '+':
			if p.arch.Family != sys.PPC64 {
				p.errorf("(register+register) not supported on this architecture")
				return
			}
		}
		name := p.next().String()
		r2, ok = p.registerReference(name)
		if !ok {
			return
		}
	}
	if p.peek() == '*' {
		// Scale 
		p.next()
		scale = p.parseScale(p.next().String())
	}
	return r1, r2, scale, true
}

// registerShift解析ARM/ARM64移位寄存器引用并返回编码的表示形式。
// 已知有一个寄存器（当前令牌）和一个移位运算符（偷看令牌）。
func (p *Parser) registerShift(name string, prefix rune) int64 {
	if prefix != 0 {
		p.errorf("prefix %c not allowed for shifted register: $%s", prefix, name)
	}
	// R1 op R2或R1 op常量。
	// op是：
	// “<<”==0 
	// “>>”==1 
	// “->”==2 
	// “@>”==3 
	r1, ok := p.registerReference(name)
	if !ok {
		return 0
	}
	var op int16
	switch p.next().ScanToken {
	case lex.LSH:
		op = 0
	case lex.RSH:
		op = 1
	case lex.ARR:
		op = 2
	case lex.ROT:
		// ARM64支架上的以下说明将右
		// /和ANDS、TST、BIC、BICS、EON、EOR、ORR、MVN、ORN、ORN、ORN 
		op = 3
	}
	tok := p.next()
	str := tok.String()
	var count int16
	switch tok.ScanToken {
	case scanner.Ident:
		if p.arch.Family == sys.ARM64 {
			p.errorf("rhs of shift must be integer: %s", str)
		} else {
			r2, ok := p.registerReference(str)
			if !ok {
				p.errorf("rhs of shift must be register or integer: %s", str)
			}
			count = (r2&15)<<8 | 1<<4
		}
	case scanner.Int, '(':
		p.back()
		x := int64(p.expr())
		if p.arch.Family == sys.ARM64 {
			if x >= 64 {
				p.errorf("register shift count too large: %s", str)
			}
			count = int16((x & 63) << 10)
		} else {
			if x >= 32 {
				p.errorf("register shift count too large: %s", str)
			}
			count = int16((x & 31) << 7)
		}
	default:
		p.errorf("unexpected %s in register shift", tok.String())
	}
	if p.arch.Family == sys.ARM64 {
		off, err := arch.ARM64RegisterShift(r1, op, count)
		if err != nil {
			p.errorf(err.Error())
		}
		return off
	} else {
		return int64((r1 & 15) | op<<5 | count)
	}
}

// 。
// 已知有一个寄存器（当前令牌）和一个扩展运算符（窥视令牌）。
func (p *Parser) registerExtension(a *obj.Addr, name string, prefix rune) {
	if prefix != 0 {
		p.errorf("prefix %c not allowed for shifted register: $%s", prefix, name)
	}

	reg, ok := p.registerReference(name)
	if !ok {
		p.errorf("unexpected %s in register extension", name)
		return
	}

	isIndex := false
	num := int16(0)
	isAmount := true // Amount默认为零
	ext := ""
	if p.peek() == lex.LSH {
		// （Rn）（Rm<2），移位偏移寄存器。
		ext = "LSL"
	} else {
		// /（Rn）（Rm.UXTW<1），扩展偏移寄存器。
		// Rm。UXTW<<3，扩展寄存器。
		p.get('.')
		tok := p.next()
		ext = tok.String()
	}
	if p.peek() == lex.LSH {
		// 解析扩展后应用的左移位量：<<amount 
		p.get(lex.LSH)
		tok := p.get(scanner.Int)
		amount, err := strconv.ParseInt(tok.String(), 10, 16)
		if err != nil {
			p.errorf("parsing left shift amount: %s", err)
		}
		num = int16(amount)
	} else if p.peek() == '[' {
		// 解析元素：[Index]
		p.get('[')
		tok := p.get(scanner.Int)
		index, err := strconv.ParseInt(tok.String(), 10, 16)
		p.get(']')
		if err != nil {
			p.errorf("parsing element index: %s", err)
		}
		isIndex = true
		isAmount = false
		num = int16(index)
	}

	switch p.arch.Family {
	case sys.ARM64:
		err := arch.ARM64RegisterExtension(a, ext, reg, num, isAmount, isIndex)
		if err != nil {
			p.errorf(err.Error())
		}
	default:
		p.errorf("register extension not supported on this architecture")
	}
}

// symbolReference解析已知不是寄存器的符号。
func (p *Parser) symbolReference(a *obj.Addr, name string, prefix rune) {
	// 标识符是一个名称。
	switch prefix {
	case 0:
		a.Type = obj.TYPE_MEM
	case '$':
		a.Type = obj.TYPE_ADDR
	case '*':
		a.Type = obj.TYPE_INDIR
	}

	// Parse optional<>（表示静态符号）或
	// <ABIxxx>（选择带有特定ABI的文本符号）。
	doIssueError := true
	isStatic, abi := p.symRefAttrs(name, doIssueError)

	if p.peek() == '+' || p.peek() == '-' {
		a.Offset = int64(p.expr())
	}
	if isStatic {
		a.Sym = p.ctxt.LookupStatic(name)
	} else {
		a.Sym = p.ctxt.LookupABI(name, abi)
	}
	if p.peek() == scanner.EOF {
		if prefix == 0 && p.isJump {
			// 没有前缀或后缀的符号是跳转标签。
			return
		}
		p.errorf("illegal or missing addressing mode for symbol %s", name)
		return
	}
	// Expect（SB）、（FP）、（PC）或（SP）
	p.get('(')
	reg := p.get(scanner.Ident).String()
	p.get(')')
	p.setPseudoRegister(a, reg, isStatic, prefix)
}

// setPseudoRegister为伪寄存器引用（如（SB））设置addr的名称字段。
func (p *Parser) setPseudoRegister(addr *obj.Addr, reg string, isStatic bool, prefix rune) {
	if addr.Reg != 0 {
		p.errorf("internal error: reg %s already set in pseudo", reg)
	}
	switch reg {
	case "FP":
		addr.Name = obj.NAME_PARAM
	case "PC":
		if prefix != 0 {
			p.errorf("illegal addressing mode for PC")
		}
		addr.Type = obj.TYPE_BRANCH // 我们设置了类型，并保持名称不变。看到了吗。
	case "SB":
		addr.Name = obj.NAME_EXTERN
		if isStatic {
			addr.Name = obj.NAME_STATIC
		}
	case "SP":
		addr.Name = obj.NAME_AUTO // 伪堆栈。
	default:
		p.errorf("expected pseudo-register; found %s", reg)
	}
	if prefix == '$' {
		addr.Type = obj.TYPE_ADDR
	}
}

// symrafttrs解析
// 函数符号'name'的可选函数符号属性子句，如果'issuerror'为真，则记录格式错误的
// 属性子句的错误。返回值是
// （布尔值，ABI）对，表示命名符号是
// 静态或特定ABI规范。
// 
// attribute子句的预期形式是：
// 
// empty，yielding（false，obj.ABI0）
// “<>”，屈服（true，obj.ABI0）屈服（false，obj.ABI0）屈服（false，obj.ABI0）屈服（false，obj.ABI0）屈服（false，obj.ABIInternal）屈服（false，obj.ABIInternal）屈服（false，obj.ABIInternal）屈服（false，obj.ABIInternal）屈服（false，obj.ABIInternal）屈服（false）屈服（false，obj.ABIInternal）。
// 
func (p *Parser) symRefAttrs(name string, issueError bool) (bool, obj.ABI) {
	abi := obj.ABI0
	isStatic := false
	if p.peek() != '<' {
		return isStatic, abi
	}
	p.next()
	tok := p.peek()
	if tok == '>' {
		isStatic = true
	} else if tok == scanner.Ident {
		abistr := p.get(scanner.Ident).String()
		if !p.compilingRuntime {
			if issueError {
				p.errorf("ABI selector only permitted when compiling runtime, reference was to %q", name)
			}
		} else {
			theabi, valid := obj.ParseABI(abistr)
			if !valid {
				if issueError {
					p.errorf("malformed ABI selector %q in reference to %q",
						abistr, name)
				}
			} else {
				abi = theabi
			}
		}
	}
	p.get('>')
	return isStatic, abi
}

// funcAddress解析外部函数地址。这是一种操作数语法的约束形式，始终基于SB，
// 非静态，最多有一个简单的整数偏移量：
// 
// /[$|*]sym[<abi>][+Int]（SB）
func (p *Parser) funcAddress() (string, obj.ABI, bool) {
	switch p.peek() {
	case '$', '*':
		// 跳过前缀。
		p.next()
	}

	tok := p.next()
	name := tok.String()
	if tok.ScanToken != scanner.Ident || p.atStartOfRegister(name) {
		return "", obj.ABI0, false
	}
	// Parse optional<>（表示静态符号）或
	// <ABIxxx>（选择带有特定ABI的文本符号）。
	noErrMsg := false
	isStatic, abi := p.symRefAttrs(name, noErrMsg)
	if isStatic {
		return "", obj.ABI0, false // 此函数拒绝静态符号。
	}
	tok = p.next()
	if tok.ScanToken == '+' {
		if p.next().ScanToken != scanner.Int {
			return "", obj.ABI0, false
		}
		tok = p.next()
	}
	if tok.ScanToken != '(' {
		return "", obj.ABI0, false
	}
	if reg := p.next(); reg.ScanToken != scanner.Ident || reg.String() != "SB" {
		return "", obj.ABI0, false
	}
	if p.next().ScanToken != ')' || p.peek() != scanner.EOF {
		return "", obj.ABI0, false
	}
	return name, abi, true
}

// registerIndirect解析寄存器间接寻址的一般形式。
// 它可以是（R1），（R2*刻度），（R1）（R2*刻度），（R1）（R2.SXTX<3）或（R1）（R2<3）
// 其中R1可以是简单寄存器或寄存器对R:R或（R，R）或（R+R）。
// 或者它可能是一个伪间接式（FP）。
// 我们坐在开始的括号里。
func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
	p.get('(')
	tok := p.next()
	name := tok.String()
	r1, r2, scale, ok := p.register(name, 0)
	if !ok {
		p.errorf("indirect through non-register %s", tok)
	}
	p.get(')')
	a.Type = obj.TYPE_MEM
	if r1 < 0 {
		// 伪寄存器引用。
		if r2 != 0 {
			p.errorf("cannot use pseudo-register in pair")
			return
		}
		// 对于SB、SP和FP，这里必须有一个名称。0（FP）不合法。
		if name != "PC" && a.Name == obj.NAME_NONE {
			p.errorf("cannot reference %s without a symbol", name)
		}
		p.setPseudoRegister(a, name, false, prefix)
		return
	}
	a.Reg = r1
	if r2 != 0 {
		// TODO:这里的编码一致性很好。
		if p.arch.InFamily(sys.ARM, sys.ARM64) {
			// 特殊形式
			// ARM:目标寄存器对（R1，R2）。
			// ARM64:LDP/STP的寄存器对（R1，R2）。
			if prefix != 0 || scale != 0 {
				p.errorf("illegal address mode for register pair")
				return
			}
			a.Type = obj.TYPE_REGREG
			a.Offset = int64(r2)
			// 后面不能有任何内容
			return
		}
		if p.arch.Family == sys.PPC64 {
			// PPC64的特殊表格：（R1+R2）；（R1）（R2*1）的别名。
			if prefix != 0 || scale != 0 {
				p.errorf("illegal address mode for register+register")
				return
			}
			a.Type = obj.TYPE_MEM
			a.Scale = 1
			a.Index = r2
			// 可能什么都不会发生。
			return
		}
	}
	if r2 != 0 {
		p.errorf("indirect through register pair")
	}
	if prefix == '$' {
		a.Type = obj.TYPE_ADDR
	}
	if r1 == arch.RPC && prefix != 0 {
		p.errorf("illegal addressing mode for PC")
	}
	if scale == 0 && p.peek() == '(' {
		// 一般形式（R）（R*scale）。
		p.next()
		tok := p.next()
		if p.atRegisterExtension() {
			p.registerExtension(a, tok.String(), prefix)
		} else if p.atRegisterShift() {
			// （R1）（R2<<3）
			p.registerExtension(a, tok.String(), prefix)
		} else {
			r1, r2, scale, ok = p.register(tok.String(), 0)
			if !ok {
				p.errorf("indirect through non-register %s", tok)
			}
			if r2 != 0 {
				p.errorf("unimplemented two-register form")
			}
			a.Index = r1
			if scale != 0 && scale != 1 && p.arch.Family == sys.ARM64 {
				// 支持（R1）（R2）（无缩放）和（R1）（R2*1）。
				p.errorf("arm64 doesn't support scaled register format")
			} else {
				a.Scale = int16(scale)
			}
		}
		p.get(')')
	} else if scale != 0 {
		if p.arch.Family == sys.ARM64 {
			p.errorf("arm64 doesn't support scaled register format")
		}
		// 第一个（R）不见了，我们只有（R*scale）。
		a.Reg = 0
		a.Index = r1
		a.Scale = int16(scale)
	}
}

// 寄存器列表解析ARM或ARM64寄存器列表表达式，即[]中的
// 寄存器列表。可能有逗号分隔的范围或单个
// 寄存器，如[R1，R3-R5]或[V1.S4，V2.S4，V3.S4，V4.S4]中的寄存器。
// 对于ARM，只能显示R0到R15。
// 对于ARM64，可能会出现带有排列的V0到V31。
// 
// For 386/AMD64寄存器列表指定4VNNIW样式的多源操作数。
// 对于4个元素的范围，英特尔手册使用“+3”符号，例如：
// VP4DPWSDS zmm1{k1}{z}，zmm2+3，m128 
// 给定asm行：
// VP4DPWSDS Z5，[Z10-Z13]，（AX）
// 只接受简单的范围，如[Z0-Z3]。
// 
// 开口支架已被消耗。
func (p *Parser) registerList(a *obj.Addr) {
	if p.arch.InFamily(sys.I386, sys.AMD64) {
		p.registerListX86(a)
	} else {
		p.registerListARM(a)
	}
}

func (p *Parser) registerListARM(a *obj.Addr) {
	// 每个循环一个范围。
	var maxReg int
	var bits uint16
	var arrangement int64
	switch p.arch.Family {
	case sys.ARM:
		maxReg = 16
	case sys.ARM64:
		maxReg = 32
	default:
		p.errorf("unexpected register list")
	}
	firstReg := -1
	nextReg := -1
	regCnt := 0
ListLoop:
	for {
		tok := p.next()
		switch tok.ScanToken {
		case ']':
			break ListLoop
		case scanner.EOF:
			p.errorf("missing ']' in register list")
			return
		}
		switch p.arch.Family {
		case sys.ARM64:
			// Vn。T 
			name := tok.String()
			r, ok := p.registerReference(name)
			if !ok {
				p.errorf("invalid register: %s", name)
			}
			reg := r - p.arch.Register["V0"]
			p.get('.')
			tok := p.next()
			ext := tok.String()
			curArrangement, err := arch.ARM64RegisterArrangement(reg, name, ext)
			if err != nil {
				p.errorf(err.Error())
			}
			if firstReg == -1 {
				// 只记录第一个寄存器和排列
				firstReg = int(reg)
				nextReg = firstReg
				arrangement = curArrangement
			} else if curArrangement != arrangement {
				p.errorf("inconsistent arrangement in ARM64 register list")
			} else if nextReg != int(reg) {
				p.errorf("incontiguous register in ARM64 register list: %s", name)
			}
			regCnt++
			nextReg = (nextReg + 1) % 32
		case sys.ARM:
			// 解析上界和下界。
			lo := p.registerNumber(tok.String())
			hi := lo
			if p.peek() == '-' {
				p.next()
				hi = p.registerNumber(p.next().String())
			}
			if hi < lo {
				lo, hi = hi, lo
			}
			// 检查寄存器列表中没有重复项。
			for i := 0; lo <= hi && i < maxReg; i++ {
				if bits&(1<<lo) != 0 {
					p.errorf("register R%d already in list", lo)
				}
				bits |= 1 << lo
				lo++
			}
		default:
			p.errorf("unexpected register list")
		}
		if p.peek() != ']' {
			p.get(',')
		}
	}
	a.Type = obj.TYPE_REGLIST
	switch p.arch.Family {
	case sys.ARM:
		a.Offset = int64(bits)
	case sys.ARM64:
		offset, err := arch.ARM64RegisterListOffset(firstReg, regCnt, arrangement)
		if err != nil {
			p.errorf(err.Error())
		}
		a.Offset = offset
	default:
		p.errorf("register list not supported on this architecuture")
	}
}

func (p *Parser) registerListX86(a *obj.Addr) {
	// 只接受[RegA RegB]语法。
	// 不要使用p.get（）来提供更好的错误消息。

	loName := p.next().String()
	lo, ok := p.arch.Register[loName]
	if !ok {
		if loName == "EOF" {
			p.errorf("register list: expected ']', found EOF")
		} else {
			p.errorf("register list: bad low register in `[%s`", loName)
		}
		return
	}
	if tok := p.next().ScanToken; tok != '-' {
		p.errorf("register list: expected '-' after `[%s`, found %s", loName, tok)
		return
	}
	hiName := p.next().String()
	hi, ok := p.arch.Register[hiName]
	if !ok {
		p.errorf("register list: bad high register in `[%s-%s`", loName, hiName)
		return
	}
	if tok := p.next().ScanToken; tok != ']' {
		p.errorf("register list: expected ']' after `[%s-%s`, found %s", loName, hiName, tok)
	}

	a.Type = obj.TYPE_REGLIST
	a.Reg = lo
	a.Offset = x86.EncodeRegisterRange(lo, hi)
}

// 寄存器号是特定于ARM的。它返回指定寄存器的编号。
func (p *Parser) registerNumber(name string) uint16 {
	if p.arch.Family == sys.ARM && name == "g" {
		return 10
	}
	if name[0] != 'R' {
		p.errorf("expected g or R0 through R15; found %s", name)
		return 0
	}
	r, ok := p.registerReference(name)
	if !ok {
		return 0
	}
	reg := r - p.arch.Register["R0"]
	if reg < 0 {
		// 对于具有以R为前缀的其他寄存器的体系结构，可能会发生这种情况。
		p.errorf("expected g or R0 through R15; found %s", name)
		return 0
	}
	return uint16(reg)
}

// 注意：与旧的yacc/C实现相比，这里的表达式处理有两个变化。
// 也没有太多实际的结果，因为我们在汇编代码中看到的表达式很简单，但作为记录：
// 
// 1）求值使用uint64；旧的那个用int64。
// 2）优先级使用Go规则而不是C规则。

// expr=term | term（“+”|“-”|“|”|“^”）term。
func (p *Parser) expr() uint64 {
	value := p.term()
	for {
		switch p.peek() {
		case '+':
			p.next()
			value += p.term()
		case '-':
			p.next()
			value -= p.term()
		case '|':
			p.next()
			value |= p.term()
		case '^':
			p.next()
			value ^= p.term()
		default:
			return value
		}
	}
}

// flootxper=fconst |“-”flootxper |“+”flootxpr |“（“flootxpr”）“
func (p *Parser) floatExpr() float64 {
	tok := p.next()
	switch tok.ScanToken {
	case '(':
		v := p.floatExpr()
		if p.next().ScanToken != ')' {
			p.errorf("missing closing paren")
		}
		return v
	case '+':
		return +p.floatExpr()
	case '-':
		return -p.floatExpr()
	case scanner.Float:
		return p.atof(tok.String())
	}
	p.errorf("unexpected %s evaluating float expression", tok)
	return 0
}

// term=factor | factor（“*”|“/”|“%”factor（<<“|”和“）factor 
func (p *Parser) term() uint64 {
	value := p.factor()
	for {
		switch p.peek() {
		case '*':
			p.next()
			value *= p.factor()
		case '/':
			p.next()
			if int64(value) < 0 {
				p.errorf("divide of value with high bit set")
			}
			divisor := p.factor()
			if divisor == 0 {
				p.errorf("division by zero")
			} else {
				value /= divisor
			}
		case '%':
			p.next()
			divisor := p.factor()
			if int64(value) < 0 {
				p.errorf("modulo of value with high bit set")
			}
			if divisor == 0 {
				p.errorf("modulo by zero")
			} else {
				value %= divisor
			}
		case lex.LSH:
			p.next()
			shift := p.factor()
			if int64(shift) < 0 {
				p.errorf("negative left shift count")
			}
			return value << shift
		case lex.RSH:
			p.next()
			shift := p.term()
			if int64(shift) < 0 {
				p.errorf("negative right shift count")
			}
			if int64(value) < 0 {
				p.errorf("right shift of value with high bit set")
			}
			value >>= shift
		case '&':
			p.next()
			value &= p.factor()
		default:
			return value
		}
	}
}

// factor=const”+“factor |“，”factor |“-”factor | factor | factor |“/”factor | factor | factor | factor | factor |返回值必须是正的。
func (p *Parser) factor() uint64 {
	tok := p.next()
	switch tok.ScanToken {
	case scanner.Int:
		return p.atoi(tok.String())
	case scanner.Char:
		str, err := strconv.Unquote(tok.String())
		if err != nil {
			p.errorf("%s", err)
		}
		r, w := utf8.DecodeRuneInString(str)
		if w == 1 && r == utf8.RuneError {
			p.errorf("illegal UTF-8 encoding for character constant")
		}
		return uint64(r)
	case '+':
		return +p.factor()
	case '-':
		return -p.factor()
	case '~':
		return ^p.factor()
	case '(':
		v := p.expr()
		if p.next().ScanToken != ')' {
			p.errorf("missing closing paren")
		}
		return v
	}
	p.errorf("unexpected %s evaluating expression", tok)
	return 0
}

func (p *Parser) positiveAtoi(str string) int64 {
	value, err := strconv.ParseInt(str, 0, 64)
	if err != nil {
		p.errorf("%s", err)
	}
	if value < 0 {
		p.errorf("%s overflows int64", str)
	}
	return value
}

func (p *Parser) atoi(str string) uint64 {
	value, err := strconv.ParseUint(str, 0, 64)
	if err != nil {
		p.errorf("%s", err)
	}
	return value
}

func (p *Parser) atof(str string) float64 {
	value, err := strconv.ParseFloat(str, 64)
	if err != nil {
		p.errorf("%s", err)
	}
	return value
}

// EOF代表输入的结束。
var EOF = lex.Make(scanner.EOF, "EOF")

func (p *Parser) next() lex.Token {
	if !p.more() {
		return EOF
	}
	tok := p.input[p.inputPos]
	p.inputPos++
	return tok
}

func (p *Parser) back() {
	if p.inputPos == 0 {
		p.errorf("internal error: backing up before BOL")
	} else {
		p.inputPos--
	}
}

func (p *Parser) peek() lex.ScanToken {
	if p.more() {
		return p.input[p.inputPos].ScanToken
	}
	return scanner.EOF
}

func (p *Parser) more() bool {
	return p.inputPos < len(p.input)
}

// get验证下一项是否具有预期的类型并返回它。
func (p *Parser) get(expected lex.ScanToken) lex.Token {
	p.expect(expected, expected.String())
	return p.next()
}

// ExpectOperatureEnd验证解析状态是否正确位于操作数的末尾。
func (p *Parser) expectOperandEnd() {
	p.expect(scanner.EOF, "end of operand")
}

// expect验证下一项是否具有预期的类型。它不会消耗它。
func (p *Parser) expect(expectedToken lex.ScanToken, expectedMessage string) {
	if p.peek() != expectedToken {
		p.errorf("expected %s, found %s", expectedMessage, p.next())
	}
}

// have报告剩余令牌（包括当前令牌）是否包含指定的令牌。
func (p *Parser) have(token lex.ScanToken) bool {
	for i := p.inputPos; i < len(p.input); i++ {
		if p.input[i].ScanToken == token {
			return true
		}
	}
	return false
}

// at报告下一个令牌是否符合要求。
func (p *Parser) at(next ...lex.ScanToken) bool {
	if len(p.input)-p.inputPos < len(next) {
		return false
	}
	for i, r := range next {
		if p.input[p.inputPos+i].ScanToken != r {
			return false
		}
	}
	return true
}
